## @package auto_vm
#  Module auto_vm for working with VMWare virtual machines. @author Ivan Filippov (filippov@paragon-software.com)
#
#  @file auto_vm.py source file for module auto_vm
import auto_log
import auto_utility
import os
import time

ID_VM_START = "vm_start"
ID_VM_STOP = "vm_stop"
ID_VM_VMX_UPDATE = "vm_vmx_update"
ID_VM_NAME_FROM_VMX = "vm_name_from_vmx"
ID_VM_CHECK_NEW_SNAPSHOT_NAME = "vm_check_new_snapshot_name"
ID_VM_IS_SNAPSHOT_UNIQUE = "vm_is_snapshot_unique"
ID_VM_REVERT = "vm_revert"
ID_VMDK_FROM_VMX = "vmdk_from_vmx"
ID_VM_MOUNT = "vm_mount"
ID_VM_MOUNT_WINDOWS_VMDK = "vm_mount_windows_vmdk"
ID_VM_UNMOUNT = "vm_unmount"
ID_VM_CREATE_SNAPSHOT = "vm_create_snapshot"
ID_VM_DELETE_SNAPSHOT = "vm_delete_snapshot"
ID_VM_MOUNT_WINDOWS_VMX = "vm_mount_windows_vmx"
ID_VM_WAIT_AND_MOUNT_VMX = "vm_wait_and_mount_vmx"

## <b>Description:</b> The function starts virtual machine.
#  
#  The function starts virtual machine.
#  In case of success it returns integer value = 0.
#  In case of error it returns the string value = error description line.
#  @param vmrun
#  string value = path to vmrun.exe
#  @param vmx
#  string value = path to *.vmx file
#  @param log
#  string value = path to file for logging. Default value auto_log.LOG_TO_STDOUT - log to stdout. 
#  Also you can use auto_log.LOG_TO_NONE to disable logging.
#  
## <b>Example:</b>
#  <br>@code
#from auto_vm import vm_start
#
#vmrun = r"C:\Program Files\VMware\VMware Workstation\vmrun.exe"
#vmx = r"e:\VMStuff\7\64\7_64_Ultimate\7_64_Ultimate.vmx"
#
#result = vm_start(vmrun, vmx, "c:\\logs\\log.xml")
#if result != 0:
#    print("Can't start vmware. Error = ", result)
#else:
#    print("Vmware is started succesfully!")
#@endcode
def vm_start(vmrun, vmx, log = auto_log.LOG_TO_STDOUT):
    id = ID_VM_START
    #--------------------------------------------------
    result = auto_utility.check_paths_exists([vmrun, vmx])
    if result != 0:
        message = result
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    vmx_update_result = vm_vmx_update(vmx, log)
    if vmx_update_result != 0:
        message = "Can't start vmware\n"
        message = message + vmx_update_result
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    vm_start = '"%s" start "%s"' % (vmrun, vmx)
    start_result = auto_log.get_cmd_output2(vm_start)
    if start_result["err"] == 0:
        return 0
    else:
        message = "path to vmrun.exe = " + vmrun
        message = message + "\npath to vmware *.vmx file = " + vmx
        message = message + "\nCan't start vmware. Error code = " + str(start_result["err"])
        message = message + "\nCan't start vmware. Output = " + start_result["out"]
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
#----------------------------------------------------------------------

## <b>Description:</b> The function stops virtual machine.
#  
#  The function stops virtual machine.
#  In case of success it returns integer value = 0.
#  In case of error it returns the string value = error description line.
#  @param vmrun
#  string value = path to vmrun.exe
#  @param vmx
#  string value = path to *.vmx file
#  @param log
#  string value = path to file for logging. Default value auto_log.LOG_TO_STDOUT - log to stdout. 
#  Also you can use auto_log.LOG_TO_NONE to disable logging.
#  
## <b>Example:</b>
#  <br>@code
#from auto_vm import vm_stop
#
#vmrun = r"C:\Program Files\VMware\VMware Workstation\vmrun.exe"
#vmx = r"e:\VMStuff\7\64\7_64_Ultimate\7_64_Ultimate.vmx"
#
#result = vm_stop(vmrun, vmx, "c:\\logs\\log.xml")
#if result != 0:
#    print("Can't stop vmware. Error = ", result)
#else:
#    print("Vmware is stopped succesfully!")
#@endcode
def vm_stop(vmrun, vmx, log = auto_log.LOG_TO_STDOUT):
    id = ID_VM_STOP
    #--------------------------------------------------
    result = auto_utility.check_paths_exists([vmrun, vmx])
    if result != 0:
        message = result
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    vm_stop = '"%s" stop "%s" hard' % (vmrun, vmx)
    result = auto_log.get_cmd_output2(vm_stop)
    if result["err"] == 0:
        return 0
    else:
        message = "path to vmrun.exe = " + vmrun
        message = message + "\npath to vmware *.vmx file = " + vmx
        message = message + "\nCan't stop vmware. Error code = " + str(result["err"])
        message = message + "\nCan't stop vmware. Output = " + result["out"]
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
#----------------------------------------------------------------------

## <b>Description:</b> Auxiliary function (It updates *.vmx file).
#  
#  The function is used in vm_start function.
#  It updates *.vmx file for starting VMWare virtual machine without request
#  In case of success it returns integer value = 0.
#  In case of error it returns the string value = error description line.
#  @param vmx
#  string value = path to *.vmx file
#  @param log
#  string value = path to file for logging. Default value auto_log.LOG_TO_STDOUT - log to stdout. 
#  Also you can use auto_log.LOG_TO_NONE to disable logging.
def vm_vmx_update(vmx, log = auto_log.LOG_TO_STDOUT):
    id = ID_VM_VMX_UPDATE
    #--------------------------------------------------
    if not os.path.exists(vmx):
        message = "Can't update " + vmx + " file for starting VM without request\n"
        message = message + "File does not exist\n"
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    try:
        file = open(vmx, "r+")
        data = file.read()
        if data.count("uuid.action = ") == 0:
            file.write("uuid.action = \"create\"")
        file.close()
    except:
        message = "Can't update " + vmx + " file for starting VM without request\n"
        message = message + "Can't modify file\n"
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    return 0
#----------------------------------------------------------------------

## <b>Description:</b> The function gets virtual machine name from *.vmx file.
#  
#  The function gets virtual machine name from *.vmx file.
#  In case of success the function returns the dictionary value = {"err": 0, "res": name}.
#  <br>"err" is integer value = 0, "res" is string value with virtual machine name.
#  <br>In case of error the function returns the dictionary value = {"err": message, "res": ""}
#  "err" is string value with error description, "res" is empty string - "".
#  @param vmx
#  string value = path to *.vmx file
#  @param log
#  string value = path to file for logging. Default value auto_log.LOG_TO_STDOUT - log to stdout. 
#  Also you can use auto_log.LOG_TO_NONE to disable logging.
#  
## <b>Example:</b>
#  <br>@code
#from auto_vm import vm_name_from_vmx
#
#vmx = r"e:\VMStuff\7\64\7_64_Ultimate\7_64_Ultimate.vmx"
#
#result = vm_name_from_vmx(vmx)
#if result["err"] != 0:
#    print("Can't read name from vmx. Error = ", result["err"])
#else:
#    print("Vmware name = ", result["res"])
#@endcode
def vm_name_from_vmx(vmx, log = auto_log.LOG_TO_STDOUT):
    id = ID_VM_NAME_FROM_VMX
    #--------------------------------------------------
    result = auto_utility.check_paths_exists([vmx])
    if result != 0:
        message = result
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        result = {"err": message, "res": ""}
        return result
    #--------------------------------------------------
    try:
        file = open(vmx, "r")
        data = file.read()
        file.close()
        result = {"err": 0, "res": ((data.split("displayName = ")[1].split("\n")[0])[1:-1])}
        return result
    except:
        message = "Can't read vmware name from file " + vmx
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        result = {"err": message, "res": ""}
        return result
#----------------------------------------------------------------------

## <b>Description:</b> The function checks if snaphot name is used or not.
#  
#  The function checks if snaphot name is used or not.
#  In case of success the function returns the dictionary value = {"err": 0, "res": 0}.
#  <br>"err" is integer value = 0, "res" is integer value = 0.
#  <br>So the name can be used for creating new snapshot
#  <br>If name is already used the function returns the dictionary value = {"err": 0, "res": message}.
#  <br>"res" contains string value with info that snapshot is already used
#  <br>In error case the function returns the dictionary value = {"err": message, "res": ""}
#  "err" is string value with error description, "res" is empty string - "".
#  @param vmrun
#  string value = path to vmrun.exe
#  @param vmx
#  string value = path to *.vmx file
#  @param snapname
#  string value = name for checking
#  @param log
#  string value = path to file for logging. Default value auto_log.LOG_TO_STDOUT - log to stdout. 
#  Also you can use auto_log.LOG_TO_NONE to disable logging.
#  
## <b>Example:</b>
#  <br>@code
#from auto_vm import vm_check_new_snapshot_name
#
#vmrun = r"C:\Program Files\VMware\VMware Workstation\vmrun.exe"
#vmx = r"e:\VMStuff\7\64\7_64_Ultimate\7_64_Ultimate.vmx"
#snapname = "CleanInstall"
#
#result = vm_check_new_snapshot_name(vmrun, vmx, snapname)
#if result["err"] != 0:
#    print("Can't check name. Error = ", result["err"])
#elif result["res"] != 0:
#    print("Name can't be used for new snapshot ", result["res"])
#else:
#    print("Name can be used for new snapshot!")
#@endcode
def vm_check_new_snapshot_name(vmrun, vmx, snapname, log = auto_log.LOG_TO_STDOUT):
    id = ID_VM_CHECK_NEW_SNAPSHOT_NAME
    #--------------------------------------------------
    result = auto_utility.check_paths_exists([vmrun, vmx])
    if result != 0:
        message = result
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        result = {"err": message, "res": ""}
        return result
    #--------------------------------------------------
    vm_list_snapshots = '"%s" listSnapshots "%s"' % (vmrun, vmx)
    result = auto_log.get_cmd_output2(vm_list_snapshots)
    if result["err"] != 0:
        message = "Can't list snapshots"
        message = message + "\npath to vmware *.vmx file = " + vmx
        message = message + "\nvmrun.exe listSnapshots error code = " + str(result["err"])
        message = message + "\nvmrun.exe listSnapshots error output = " + result["out"]
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        result = {"err": message, "res": ""}
        return result
    #--------------------------------------------------
    count = 0
    data = result["out"].split("\n")
    if len(data) <= 1:
        return 0
    data = data[1:]
    
    for item in data:
        if item.upper() == snapname.upper():
            message = "Snapshot " + snapname + " already exists"
            message = message + "\nvmrun.exe listSnapshots output:\n" + result["out"]
            result = {"err": 0, "res": message}
            return result
    result = {"err": 0, "res": 0}
    return result
#----------------------------------------------------------------------

## <b>Description:</b> The function checks if snaphot name is unique or not.
#  
#  The function checks if snaphot name is unique or not.
#  In case of success the function returns the dictionary value = {"err": 0, "res": 0}.
#  <br>"err" is integer value = 0, "res" is integer value = 0.
#  <br>So the name is unique and we can use operations such as delete snapshot or revert to snapshot.
#  <br>If name is not unique the function returns the dictionary value = {"err": 0, "res": message}.
#  <br>"res" contains string value with info that snapshot is not unique.
#  <br>In error case the function returns the dictionary value = {"err": message, "res": ""}
#  "err" is string value with error description, "res" is empty string - "".
#  @param vmrun
#  string value = path to vmrun.exe
#  @param vmx
#  string value = path to *.vmx file
#  @param snapname
#  string value = name for checking
#  @param log
#  string value = path to file for logging. Default value auto_log.LOG_TO_STDOUT - log to stdout. 
#  Also you can use auto_log.LOG_TO_NONE to disable logging.
#  
## <b>Example:</b>
#  <br>@code
#from auto_vm import vm_is_snapshot_unique
#
#vmrun = r"C:\Program Files\VMware\VMware Workstation\vmrun.exe"
#vmx = r"e:\VMStuff\7\64\7_64_Ultimate\7_64_Ultimate.vmx"
#snapname = "CleanInstall"
#
#result = vm_is_snapshot_unique(vmrun, vmx, snapname)
#if result["err"] != 0:
#    print("Can't check name. Error = ", result["err"])
#elif result["res"] != 0:
#    print("Name is not unique ", result["res"])
#else:
#    print("Name is unique!")
#@endcode
def vm_is_snapshot_unique(vmrun, vmx, snapname, log = auto_log.LOG_TO_STDOUT):
    id = ID_VM_IS_SNAPSHOT_UNIQUE
    #--------------------------------------------------
    result = auto_utility.check_paths_exists([vmrun, vmx])
    if result != 0:
        message = result
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        result = {"err": message, "res": ""}
        return result
    #--------------------------------------------------
    vm_list_snapshots = '"%s" listSnapshots "%s"' % (vmrun, vmx)
    result = auto_log.get_cmd_output2(vm_list_snapshots)
    if result["err"] != 0:
        message = "Can't list snapshots"
        message = message + "\npath to vmware *.vmx file = " + vmx
        message = message + "\nvmrun.exe listSnapshots error code = " + str(result["err"])
        message = message + "\nvmrun.exe listSnapshots error output = " + result["out"]
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        result = {"err": message, "res": ""}
        return result
    #--------------------------------------------------
    count = 0
    data = result["out"].split("\n")
    if len(data) <= 1:
        message = "There are no snapshots at all!"
        message = message + "\nvmrun.exe listSnapshots output = " + result["out"]
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        result = {"err": 0, "res": message}
        return result
    
    data = data[1:]
    for item in data:
        if item.upper() == snapname.upper():
            count += 1
    if count == 1:
        result = {"err": 0, "res": 0}
        return result
    elif count == 0:
        message = "Snapshot does not exists"
        message = message + "\nvmrun.exe listSnapshots output = " + result["out"]
        result = {"err": 0, "res": message}
        return result
    else:
        message = "Snapshot is not unique"
        message = message + "\nvmrun.exe listSnapshots output = " + result["out"]
        result = {"err": 0, "res": message}
        return result
#----------------------------------------------------------------------

## <b>Description:</b> The function reverts virtual machine to snapshot.
#  
#  The function reverts virtual machine to snapshot.
#  In case of success it returns integer value = 0.
#  In case of error it returns the string value = error description line.
#  @param vmrun
#  string value = path to vmrun.exe
#  @param vmx
#  string value = path to *.vmx file
#  @param snapname
#  string value = snapshot name
#  @param log
#  string value = path to file for logging. Default value auto_log.LOG_TO_STDOUT - log to stdout. 
#  Also you can use auto_log.LOG_TO_NONE for disabling logging.
#  
## <b>Example:</b>
#  <br>@code
#from auto_vm import vm_revert
#
#vmrun = r"C:\Program Files\VMware\VMware Workstation\vmrun.exe"
#vmx = r"e:\VMStuff\7\64\7_64_Ultimate\7_64_Ultimate.vmx"
#
#result = vm_revert(vmrun, vmx, "Install", "c:\\logs\\revert.xml")
#if result != 0:
#    print("Can't revert vmware to snapshot. Error = ", result)
#else:
#    print("Vmware was reverted to snapshot succesfully!")
#@endcode
def vm_revert(vmrun, vmx, snapname, log = auto_log.LOG_TO_STDOUT):
    id = ID_VM_REVERT
    #--------------------------------------------------
    result = auto_utility.check_paths_exists([vmrun, vmx])
    if result != 0:
        message = result
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    result = vm_is_snapshot_unique(vmrun, vmx, snapname, auto_log.LOG_TO_NONE)
    if result["err"] != 0:
        message = "Can't revert vmware to snapshot " + snapname
        message = message + "\nvm_is_snapshot_unique error = " + result["err"]
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    if result["res"] != 0:
        message = "Can't revert vmware to snapshot " + snapname
        message = message + "\nvm_is_snapshot_unique error = " + result["res"]
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    vm_revert = '"%s" revertToSnapshot "%s" "%s"' % (vmrun, vmx, snapname)
    result = auto_log.get_cmd_output2(vm_revert)
    if result["err"] != 0:
        message = "Can't revert vmware to snapshot."
        message = message + "\npath to vmware *.vmx file = " + vmx
        message = message + "\nSnapshot name = " + snapname
        message = message + "\n vmrun.exe revertToSnapshot error code = " + str(result["err"])
        message = message + "\nvmrun.exe revertToSnapshot error output = " + result["out"]
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    else:
        return 0
#----------------------------------------------------------------------

## <b>Description:</b> The function gets the first *.vmdk name from *.vmx file.
#  
#  The function gets the first *.vmdk name from *.vmx file.
#  In case of success the function returns the dictionary value = {"err": 0, "res": name}.
#  <br>"err" is integer value = 0, "res" is string value with *.vmdk name.
#  <br>In case of error the function returns the dictionary value = {"err": message, "res": ""}
#  "err" is string value with error description, "res" is empty string - "".
#  @param vmx
#  string value = path to *.vmx file
#  @param log
#  string value = path to file for logging. Default value auto_log.LOG_TO_STDOUT - log to stdout. 
#  Also you can use auto_log.LOG_TO_NONE to disable logging.
#  
## <b>Example:</b>
#  <br>@code
#from auto_vm import vmdk_from_vmx
#
#vmx = r"e:\VMStuff\7\64\7_64_Ultimate\7_64_Ultimate.vmx"
#
#result = vmdk_from_vmx(vmx)
#if result["err"] != 0:
#    print("Can't read vmdk name from vmx. Error = ", result["err"])
#else:
#    print("vmdk name = ", result["res"])
#@endcode
def vmdk_from_vmx(vmx, log = auto_log.LOG_TO_STDOUT):
    id = ID_VMDK_FROM_VMX
    #--------------------------------------------------
    result = auto_utility.check_paths_exists([vmx])
    if result != 0:
        message = result
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        result = {"err": message, "res": ""}
        return result
    #--------------------------------------------------
    try:
        file = open(vmx, "r")
        data = file.read()
        file.close()
    except:
        message = "Can't read " + vmx
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        result = {"err": message, "res": ""}
        return result
    #--------------------------------------------------
    try:
        name = data.split(".vmdk")[0]
        name = name.split(' = "')[-1]
        name = name + ".vmdk"
        name = vmx[0:(len(vmx) - len(vmx.split("\\")[-1]))] + name
    except:
        message = "Can't read vmdk name from " + vmx
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        result = {"err": message, "res": ""}
        return result
    #--------------------------------------------------
    if not os.path.exists(name):
        message = "Found vmdk, but it does not exist"
        message = message + "\nvmdk = " + name
        message = message + "\nvmx = " + vmx
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        result = {"err": message, "res": ""}
        return result
    else:
        result = {"err": 0, "res": name}
        return result
#----------------------------------------------------------------------

## <b>Description:</b> The function mounts volume from *.vmdk.
#  
#  The function mounts volume from *.vmdk.
#  In case of success it returns integer value = 0.
#  In case of error it returns the string value = error description line.
#  @param vmmount
#  string value = path to vmware-mount.exe
#  @param letter
#  string value = letter
#  @param vmdk
#  string value = path to *.vmdk file
#  @param number
#  integer value = volume number
#  @param log
#  string value = path to file for logging. Default value auto_log.LOG_TO_STDOUT - log to stdout. 
#  Also you can use auto_log.LOG_TO_NONE to disable logging.
#  
## <b>Example:</b>
#  <br>@code
#from auto_vm import vm_mount
#
#vmmount = r"C:\Program Files\VMware\VMware Virtual Disk Development Kit\bin\vmware-mount.exe"
#vmdk = r"e:\VMStuff\7\64\7_64_Ultimate\7_64_Ultimate.vmdk"
#
#result = vm_mount(vmmount, "y:", vmdk, 1, "c:\\logs\\vmmount.xml")
#if result != 0:
#    print("Can't mount vmdk. Error = ", result)
#else:
#    print("Vmdk is mounted succesfully!")
#@endcode
def vm_mount(vmmount, letter, vmdk, number, log = auto_log.LOG_TO_STDOUT):
    id = ID_VM_MOUNT
    #--------------------------------------------------
    result = auto_utility.check_paths_exists([vmmount, vmdk])
    if result != 0:
        message = result
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    if os.path.exists(letter + "\\"):
        message = "Can't mount " + vmdk + " to letter " + letter
        message = message + "\nLetter " + letter + " is already used"
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    vm_mount = '"%s" %s "%s" /v:%s' % (vmmount, letter, vmdk, number)
    result = auto_log.get_cmd_output2(vm_mount)
    if result["err"] != 0:
        message = "Can't mount " + vmdk + " to letter " + letter
        message = message + "\nvmware mount utility error = " + str(result["err"])
        message = message + "\nvmware mount utility output = " + result["out"]
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, ID_VM_MOUNT)
        return message
    return 0
#----------------------------------------------------------------------

## <b>Description:</b> The function mounts volume with windows from *.vmdk.
#  
#  The function mounts volume with windows from *.vmdk.
#  In case of success it returns integer value = 0.
#  In case of error it returns the string value = error description line.
#  @param vmmount
#  string value = path to vmware-mount.exe
#  @param letter
#  string value = letter
#  @param vmdk
#  string value = path to *.vmdk file
#  @param log
#  string value = path to file for logging. Default value auto_log.LOG_TO_STDOUT - log to stdout. 
#  Also you can use auto_log.LOG_TO_NONE to disable logging.
#  
## <b>Example:</b>
#  <br>@code
#from auto_vm import vm_mount_windows_vmdk
#
#vmmount = r"C:\Program Files\VMware\VMware Virtual Disk Development Kit\bin\vmware-mount.exe"
#vmdk = r"e:\VMStuff\7\64\7_64_Ultimate\7_64_Ultimate.vmdk"
#
#result = vm_mount_windows_vmdk(vmmount, "y:", vmdk, "c:\\logs\\vmmount.xml")
#if result != 0:
#    print("Can't mount volume with windows. Error = ", result)
#else:
#    print("Volume with windows is mounted succesfully!")
#@endcode
def vm_mount_windows_vmdk(vmmount, letter, vmdk, log = auto_log.LOG_TO_STDOUT):
    id = ID_VM_MOUNT_WINDOWS_VMDK
    #--------------------------------------------------
    result = auto_utility.check_paths_exists([vmmount, vmdk])
    if result != 0:
        message = result
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    if os.path.exists(letter):
        message = "Letter " + letter + " is already in use"
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    i = 1
    N = 5
    while i < N:
        if vm_mount(vmmount, letter, vmdk, i, log) == 0:
            if auto_utility.search_startup_folder(letter, auto_log.LOG_TO_NONE) != "":
                return 0
            else:
                result = vm_unmount(vmmount, letter, log)
                if result != 0:
                    message = "Can't unmount letter " + letter + "while searching for volume with windows"
                    message = message + "\nvmdk = " + vmdk
                    message = message + "\nvolume number = " + str(i)
                    message = message + "\nvm_unmount output = " + result
                    auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
                    return message
        i += 1
    #--------------------------------------------------
    message = "Can't mount volume with windows"
    message = message + "\nvmdk = " + vmdk
    auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
    return message
#----------------------------------------------------------------------

## <b>Description:</b> The function mounts volume with windows from *.vmx.
#  
#  The function mounts volume with windows from *.vmx.
#  In case of success it returns integer value = 0.
#  In case of error it returns the string value = error description line.
#  @param vmmount
#  string value = path to vmware-mount.exe
#  @param letter
#  string value = letter
#  @param vmx
#  string value = path to *.vmx file
#  @param log
#  string value = path to file for logging. Default value auto_log.LOG_TO_STDOUT - log to stdout. 
#  Also you can use auto_log.LOG_TO_NONE to disable logging.
#  
## <b>Example:</b>
#  <br>@code
#from auto_vm import vm_mount_windows_vmx
#
#vmmount = r"C:\Program Files\VMware\VMware Virtual Disk Development Kit\bin\vmware-mount.exe"
#vmdk = r"e:\VMStuff\7\64\7_64_Ultimate\7_64_Ultimate.vmx"
#
#result = vm_mount_windows_vmx(vmmount, "y:", vmx, "c:\\logs\\vmmount.xml")
#if result != 0:
#    print("Can't mount volume with windows. Error = ", result)
#else:
#    print("Volume with windows is mounted succesfully!")
#@endcode
def vm_mount_windows_vmx(vmmount, letter, vmx, log = auto_log.LOG_TO_STDOUT):
    id = ID_VM_MOUNT_WINDOWS_VMX
    #--------------------------------------------------
    result = auto_utility.check_paths_exists([vmmount, vmx])
    if result != 0:
        message = result
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    if os.path.exists(letter):
        message = "Letter " + letter + " is already in use"
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    result = vmdk_from_vmx(vmx)
    if result["err"] != 0:
        message = result["err"]
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    vmdk = result["res"]
    #--------------------------------------------------
    result = vm_mount_windows_vmdk(vmmount, letter, vmdk, auto_log.LOG_TO_NONE)
    if result != 0:
        message = result
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    return 0
#----------------------------------------------------------------------

## <b>Description:</b> The function tries to mount the volume with windows from *.vmx.
#  
#  The function tries to mount the volume with windows from *.vmx every 30 seconds.
#  In case of success it returns integer value = 0. If mounting fails after limit 
#  seconds the function returns the string value = error description line.
#  @param vmmount
#  string value = path to vmware-mount.exe
#  @param letter
#  string value = letter
#  @param vmx
#  string value = path to *.vmx file
#  @param limit
#  integer value = limit in seconds. If mounting fails after limit seconds the function returns error.
#  @param log
#  string value = path to file for logging. Default value auto_log.LOG_TO_STDOUT - log to stdout. 
#  Also you can use auto_log.LOG_TO_NONE to disable logging.
#  
## <b>Example:</b>
#  <br>@code
#from auto_vm import vm_wait_and_mount_vmx
#
#vmmount = r"C:\Program Files\VMware\VMware Virtual Disk Development Kit\bin\vmware-mount.exe"
#vmdk = r"e:\VMStuff\7\64\7_64_Ultimate\7_64_Ultimate.vmx"
#
#result = vm_wait_and_mount_vmx(vmmount, "y:", vmx, 600, "c:\\logs\\vmmount.xml")
#if result != 0:
#    print("Can't mount volume with windows. Error = ", result)
#else:
#    print("Volume with windows is mounted succesfully!")
#@endcode
def vm_wait_and_mount_vmx(vmmount, letter, vmx, limit, log = auto_log.LOG_TO_STDOUT):
    id = ID_VM_WAIT_AND_MOUNT_VMX
    #--------------------------------------------------
    TIME_LONG = 90
    TIME_SHORT = 30
    total_time_limit = limit#return error if vmware works more than total_time_limit seconds
    time.sleep(TIME_LONG)
    time_count = TIME_LONG
    print("\nMount ", vmx, " to ", letter, ".")
    #--------------------------------------------------
    while vm_mount_windows_vmx(vmmount, letter, vmx, auto_log.LOG_TO_NONE) != 0:
        print("\nVmware is running for", time_count, " seconds. Please wait for another ", TIME_SHORT, " seconds.")
        time.sleep(TIME_SHORT)
        time_count += TIME_SHORT
        if time_count > total_time_limit:
            return "\nVMware works more than ", total_time_limit, " seconds.\nIt's too long - stop this operation"
    #--------------------------------------------------
    print("\nMount ", vmx, " to ", letter, ". Done!\n")
    return 0
#----------------------------------------------------------------------

## <b>Description:</b> The function unmounts volume mounted with vmware-mount.exe.
#  
#  The function unmounts volume mounted with vmware-mount.exe.
#  In case of success it returns integer value = 0.
#  In case of error it returns the string value = error description line.
#  @param vmmount
#  string value = path to vmware-mount.exe
#  @param letter
#  string value = letter
#  @param log
#  string value = path to file for logging. Default value auto_log.LOG_TO_STDOUT - log to stdout. 
#  Also you can use auto_log.LOG_TO_NONE to disable logging.
#  
## <b>Example:</b>
#  <br>@code
#from auto_vm import vm_unmount
#
#vmmount = r"C:\Program Files\VMware\VMware Virtual Disk Development Kit\bin\vmware-mount.exe"
#
#result = vm_unmount(vmmount, "y:")
#if result != 0:
#    print("Can't unmount. Error = ", result)
#else:
#    print("Unmount completed succesfully!")
#@endcode
def vm_unmount(vmmount, letter, log = auto_log.LOG_TO_STDOUT):
    id = ID_VM_UNMOUNT
    #--------------------------------------------------
    if not os.path.exists(vmmount):
        message = "Can't unmount letter " + letter
        message = message + "\nCan't open " + vmmount
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    if not os.path.exists(letter):
        message = "Can't unmount letter. " + letter + " is not in use"
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    vm_unmount = '"%s" %s /d /f' % (vmmount, letter)
    result = auto_log.get_cmd_output2(vm_unmount)
    if result["err"] != 0:
        message = "Can't unmount letter " + letter
        message = message + "\nvmware mount utility error = " + str(result["err"])
        message = message + "\nvmware mount utility output = " + result["out"]
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    return 0
#----------------------------------------------------------------------

## <b>Description:</b> The function creates snapshot for virtual machine.
#  
#  The function creates snapshot for virtual machine.
#  In case of success it returns integer value = 0.
#  In case of error it returns the string value = error description line.
#  @param vmrun
#  string value = path to vmrun.exe
#  @param vmx
#  string value = path to *.vmx file
#  @param snapname
#  string value = snapshot name
#  @param log
#  string value = path to file for logging. Default value auto_log.LOG_TO_STDOUT - log to stdout. 
#  Also you can use auto_log.LOG_TO_NONE to disable logging.
#  
## <b>Example:</b>
#  <br>@code
#from auto_vm import vm_create_snapshot
#
#vmrun = r"C:\Program Files\VMware\VMware Workstation\vmrun.exe"
#vmx = r"e:\VMStuff\7\64\7_64_Ultimate\7_64_Ultimate.vmx"
#
#result = vm_create_snapshot(vmrun, vmx, "Test")
#if result != 0:
#    print("Can't create snapshot. Error = ", result)
#else:
#    print("Snapshot is created succesfully!")
#@endcode
def vm_create_snapshot(vmrun, vmx, snapname, log = auto_log.LOG_TO_STDOUT):
    id = ID_VM_CREATE_SNAPSHOT
    #--------------------------------------------------
    result = auto_utility.check_paths_exists([vmrun, vmx])
    if result != 0:
        message = result
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    result = vm_check_new_snapshot_name(vmrun, vmx, snapname, auto_log.LOG_TO_NONE)
    if result["err"] != 0:
        message = result["err"]
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    if result["res"] != 0:
        message = result["res"]
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    vm_create_snapshot = '"%s" snapshot "%s" "%s"' % (vmrun, vmx, snapname)
    result = auto_log.get_cmd_output2(vm_create_snapshot)
    if result["err"] != 0:
        message = "Can't create snapshot."
        message = message + "\nPath to vmx = " + vmx
        message = message + "\nSnapshot name = " + snapname
        message = message + "\nvmrun utility error = " + str(result["err"])
        message = message + "\nvmrun utility output = " + result["out"]
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    return 0
#----------------------------------------------------------------------

## <b>Description:</b> The function deletes snapshot from virtual machine.
#  
#  The function deletes snapshot from virtual machine.
#  In case of success it returns integer value = 0.
#  In case of error it returns the string value = error description line.
#  @param vmrun
#  string value = path to vmrun.exe
#  @param vmx
#  string value = path to *.vmx file
#  @param snapname
#  string value = snapshot name
#  @param log
#  string value = path to file for logging. Default value auto_log.LOG_TO_STDOUT - log to stdout. 
#  Also you can use auto_log.LOG_TO_NONE to disable logging.
#  
## <b>Example:</b>
#  <br>@code
#from auto_vm import vm_delete_snapshot
#
#vmrun = r"C:\Program Files\VMware\VMware Workstation\vmrun.exe"
#vmx = r"e:\VMStuff\7\64\7_64_Ultimate\7_64_Ultimate.vmx"
#
#result = vm_delete_snapshot(vmrun, vmx, "Test")
#if result != 0:
#    print("Can't delete snapshot. Error = ", result)
#else:
#    print("Snapshot is deleted succesfully!")
#@endcode
def vm_delete_snapshot(vmrun, vmx, snapname, log = auto_log.LOG_TO_STDOUT):
    id = ID_VM_DELETE_SNAPSHOT
    #--------------------------------------------------
    result = auto_utility.check_paths_exists([vmrun, vmx])
    if result != 0:
        message = result
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    result = vm_is_snapshot_unique(vmrun, vmx, snapname, auto_log.LOG_TO_NONE)
    if result["err"] != 0:
        message = result["err"]
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    if result["res"] != 0:
        message = result["res"]
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    #--------------------------------------------------
    vm_delete = '"%s" deleteSnapshot "%s" "%s"' % (vmrun, vmx, snapname)
    result = auto_log.get_cmd_output2(vm_delete)
    if result["err"] != 0:
        message = "Can't delete snapshot."
        message = message + "\npath to vmware *.vmx file = " + vmx
        message = message + "\nSnapshot name = " + snapname
        message = message + "\n vmrun.exe deleteSnapshot error code = " + str(result["err"])
        message = message + "\nvmrun.exe deleteSnapshot error output:\n" + result["out"]
        auto_log.write_result(log, message, auto_log.STATUS_ERROR, id)
        return message
    else:
        return 0
#----------------------------------------------------------------------
